using System;
using System.Collections.Generic;
using System.IO;

enum EntryType { Folder, File }

abstract class FileSystemEntry
{
    public string Name { get; set; }
    public Folder Parent { get; set; }
    public abstract EntryType Type { get; }

    protected FileSystemEntry(string name, Folder parent = null)
    {
        Name = name;
        Parent = parent;
    }

    public abstract void Display();
}

class FileEntry : FileSystemEntry
{
    public override EntryType Type => EntryType.File;

    public FileEntry(string name, Folder parent) : base(name, parent) { }

    public override void Display()
    {
        Console.WriteLine($"[F] {Name}");
    }
}

class Folder : FileSystemEntry
{
    private List<FileSystemEntry> _entries = new List<FileSystemEntry>();

    public override EntryType Type => EntryType.Folder;

    public Folder(string name, Folder parent = null) : base(name, parent) { }

    public override void Display()
    {
        Console.WriteLine($"[D] {Name}");
        foreach (var entry in _entries)
        {
            Console.WriteLine($" - {entry.Name} ({entry.Type})");
        }
    }

    public bool Exists(string name) => _entries.Exists(e => e.Name == name);

    public FileSystemEntry Find(string name) => _entries.Find(e => e.Name == name);

    public void Add(FileSystemEntry entry)
    {
        if (Exists(entry.Name))
        {
            Console.WriteLine("Entry already exists.");
            return;
        }
        _entries.Add(entry);
    }

    public void Remove(string name)
    {
        var entry = Find(name);
        if (entry == null)
        {
            Console.WriteLine("Entry not found.");
            return;
        }

        if (entry is Folder f && f._entries.Count > 0)
        {
            Console.Write($"Delete folder '{name}' with contents? (y/n): ");
            if (Console.ReadLine()?.ToLower() != "y") return;
        }

        if (entry is FileEntry && File.Exists(entry.Name))
        {
            File.Delete(entry.Name);
        }

        _entries.Remove(entry);
        Console.WriteLine($"Removed: {name}");
    }

    public List<FileSystemEntry> GetEntries() => _entries;
}

class FileSystemManager
{
    private Folder root = new Folder("C:");
    private Folder current;

    public FileSystemManager()
    {
        current = root;
    }

    public void Run()
    {
        while (true)
        {
            Console.Write($"{GetPath()}> ");
            var input = Console.ReadLine()?.Trim();
            if (string.IsNullOrWhiteSpace(input)) continue;

            var parts = input.Split(' ', 2);
            var cmd = parts[0].ToLower();
            var arg = parts.Length > 1 ? parts[1] : "";

            switch (cmd)
            {
                case "ls": current.Display(); break;
                case "cd": ChangeDirectory(arg); break;
                case "mkdir": Create(arg, EntryType.Folder); break;
                case "touch": Create(arg, EntryType.File); break;
                case "rm": RemoveEntry(arg); break;
                case "cat": ShowFile(arg); break;
                case "help": ShowHelp(); break;
                case "exit": return;
                default: Console.WriteLine("Unknown command. Type 'help' for available commands."); break;
            }
        }
    }

    void Create(string name, EntryType type)
    {
        if (current.Exists(name))
        {
            Console.WriteLine("Entry already exists.");
            return;
        }

        if (type == EntryType.File)
        {
            File.WriteAllText(name, "");
            current.Add(new FileEntry(name, current));
        }
        else
        {
            current.Add(new Folder(name, current));
        }
    }

    void RemoveEntry(string name)
    {
        current.Remove(name);
    }

    void ChangeDirectory(string target)
    {
        if (target == "..")
        {
            current = current.Parent ?? current;
        }
        else if (target == "/")
        {
            current = root;
        }
        else
        {
            var found = current.Find(target);
            if (found is Folder folder)
                current = folder;
            else
                Console.WriteLine("Folder not found.");
        }
    }

    void ShowFile(string name)
    {
        var entry = current.Find(name);
        if (entry is FileEntry)
        {
            if (File.Exists(name))
                Console.WriteLine(File.ReadAllText(name));
            else
                Console.WriteLine("[Empty file]");
        }
        else
        {
            Console.WriteLine("File not found.");
        }
    }

    void ShowHelp()
    {
        Console.WriteLine("""
            Commands:
            ls           List contents
            cd <name>    Change directory (.. or / for root)
            mkdir <name> Create folder
            touch <name> Create file
            rm <name>    Delete entry
            cat <name>   View file contents
            help         Show help
            exit         Quit
            """);
    }

    string GetPath()
    {
        var path = new List<string>();
        var currentFolder = current;
        while (currentFolder != null)
        {
            path.Insert(0, currentFolder.Name);
            currentFolder = currentFolder.Parent;
        }
        return string.Join("\\", path);
    }
}

class Program
{
    static void Main()
    {
        new FileSystemManager().Run();
    }
}
